﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;

namespace TARLib
{
    public class Vassoio
    {
        public Vassoio(int? vassoioID, int comandaID, int progressivo, int nTotaleVassoi, int puntoDistribuzioneID, string tavoloAssegnato, string codiceComanda, string note, DateTime dataOra, string autore, ProdottoOrdinatoCollection prodotti, bool isConsegnato)
        {
            VassoioID = vassoioID;
            ComandaID = comandaID;
            Progressivo = progressivo;
            NTotaleVassoi = nTotaleVassoi;
            PuntoDistribuzioneID = puntoDistribuzioneID;
            TavoloAssegnato = tavoloAssegnato;
            CodiceComanda = codiceComanda;
            Note = note;
            DataOra = dataOra;
            Autore = autore;
            ComandaID = comandaID;
            Prodotti = prodotti;
            IsConsegnato = isConsegnato;
        }

        public Vassoio(int vassoioID)
        {
            // Costruttore dall'ID
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_Vassoio_S]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("@VassoioID", System.Data.SqlDbType.Int) { Value = vassoioID });

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                if (dr.Read())
                {
                    this.VassoioID = (int)dr["VassoioID"];
                    this.ComandaID = (int)dr["ComandaID"];
                    this.Progressivo = (int)dr["Progressivo"];
                    this.NTotaleVassoi = (int)dr["NTotaleVassoi"];
                    this.PuntoDistribuzioneID = (int)dr["PuntoDistribuzioneID"];
                    this.TavoloAssegnato = dr["TavoloAssegnato"] == DBNull.Value ? null : dr["TavoloAssegnato"].ToString();
                    this.CodiceComanda = dr["CodiceComanda"].ToString();
                    this.Note = dr["Note"] == DBNull.Value ? null : dr["Note"].ToString();
                    this.DataOra = (DateTime)dr["DataOra"];
                    this.Autore = dr["Autore"].ToString();
                    this.Prodotti = new ProdottoOrdinatoCollection();
                    this.IsConsegnato = (bool)dr["IsConsegnato"];
                }
                else
                {
                    throw new Exception("Nessun vassoio trovato con ID " + vassoioID.ToString());
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            // A questo punto carica le collection associate
            this.Prodotti.CaricaDaVassoioID(vassoioID);
        }

        public int? VassoioID { get; set; }
        public int ComandaID { get; set; }
        public int Progressivo { get; set; }
        public int NTotaleVassoi { get; set; }
        public int PuntoDistribuzioneID { get; set; }
        public string TavoloAssegnato { get; set; }
        public string CodiceComanda { get; set; }
        public string Note { get; set; }
        public DateTime DataOra { get; set; }
        public string Autore { get; set; }
        public ProdottoOrdinatoCollection Prodotti { get; set; }
        public bool IsConsegnato { get; set; }

        #region Calcolati
        public PuntoDistribuzione PuntoDiDistribuzione
        {
            get
            {
                if (Prodotti.Count == 0)
                    return null;
                else
                {
                    if (Prodotti.Select(o => o.PuntoDiDistribuzione).Any(o => o.PuntoDistribuzioneID != Prodotti.Last().PuntoDiDistribuzione.PuntoDistribuzioneID))
                    {
                        throw new Exception("Più punti di distribuzione definiti per il vassoio comanda " + ComandaID.ToString());
                    }
                    else
                    {
                        return Prodotti.Last().PuntoDiDistribuzione;
                    }
                }
            }
        }

        public VoceComandaCollection VociComanda
        {
            get
            {
                VoceComandaCollection retValue = new VoceComandaCollection();

                foreach (ProdottoOrdinato po in Prodotti)
                {
                    // Raggruppa per "Nome prodotto / Note"
                    if (retValue.Any(o => o.NomeProdotto == po.Nome && o.Note == po.Note))
                    {
                        retValue.Where(o => o.NomeProdotto == po.Nome && o.Note == po.Note).First().Quantita++;
                        retValue.Where(o => o.NomeProdotto == po.Nome && o.Note == po.Note).First().SubTotale += po.PrezzoVendita;
                    }
                    else
                    {
                        retValue.Add(new VoceComanda(1, po.Nome, po.Note, po.PrezzoVendita));
                    }
                }

                return retValue;
            }
        }

        public string DescrizioneCompleta
        {
            get
            {
                string retValue = "";

                retValue += "VASSOIO " + Progressivo.ToString();
                retValue += "\nPRODOTTI: " + Prodotti.Count.ToString() + "\n";
                foreach (VoceComanda v in VociComanda)
                {
                    retValue += String.Format("   {0} x {1} {2}\n", v.Quantita, v.NomeProdotto, v.Note);
                }

                return retValue;
            }
        }
        #endregion

        public void Salva(SqlTransaction trans)
        {
            // Salvataggio (in transazione)
            // Aggiorna l'orario
            this.DataOra = DateTime.Now;

            // Salvataggio su DB
            SqlCommand cmd = new SqlCommand();
            cmd.Transaction = trans;
            cmd.Connection = trans.Connection;
            cmd.CommandText = "[Cucina].[SP_Vassoio_I]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.Add(new SqlParameter("@VassoioID", System.Data.SqlDbType.Int) { Direction = System.Data.ParameterDirection.Output });
            cmd.Parameters.Add(new SqlParameter("@ComandaID", System.Data.SqlDbType.Int) { Value = ComandaID });
            cmd.Parameters.Add(new SqlParameter("@CodiceComanda", System.Data.SqlDbType.NVarChar, 20) { Value = CodiceComanda });
            cmd.Parameters.Add(new SqlParameter("@Progressivo", System.Data.SqlDbType.Int) { Value = Progressivo });
            cmd.Parameters.Add(new SqlParameter("@NTotaleVassoi", System.Data.SqlDbType.Int) { Value = NTotaleVassoi });
            cmd.Parameters.Add(new SqlParameter("@PuntoDistribuzioneID", System.Data.SqlDbType.Int) { Value = PuntoDiDistribuzione.PuntoDistribuzioneID });
            cmd.Parameters.Add(new SqlParameter("@TavoloAssegnato", System.Data.SqlDbType.NVarChar, 20));
            if (TavoloAssegnato == null)
                cmd.Parameters["@TavoloAssegnato"].Value = DBNull.Value;
            else
                cmd.Parameters["@TavoloAssegnato"].Value = TavoloAssegnato;

            cmd.Parameters.Add(new SqlParameter("@Note", System.Data.SqlDbType.NVarChar, 4000));
            if (Note == null)
                cmd.Parameters["@Note"].Value = DBNull.Value;
            else
                cmd.Parameters["@Note"].Value = Note;

            cmd.Parameters.Add(new SqlParameter("@DataOra", System.Data.SqlDbType.DateTime) { Value = DataOra });
            cmd.Parameters.Add(new SqlParameter("@Autore", System.Data.SqlDbType.NVarChar, 200) { Value = Autore });

            try
            {
                cmd.ExecuteNonQuery();
                VassoioID = (int)cmd.Parameters["@VassoioID"].Value;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cmd.Dispose();
            }

            // Salva i prodottiAssociati
            Prodotti.SalvaByVassoioID(VassoioID.Value, trans);
        }

        public void OttieniStampa(ref System.Drawing.Printing.PrintPageEventArgs e, TipoStampa tipoStampa)
        {
            System.Drawing.Font EtichettaFont = new System.Drawing.Font("Arial", 12);
            System.Drawing.Font PuntoDistribuzioneFont = new System.Drawing.Font("Arial", 16, System.Drawing.FontStyle.Bold);
            System.Drawing.Font EvidenziatoFont = new System.Drawing.Font("Arial", 13, System.Drawing.FontStyle.Bold);
            System.Drawing.Font NoteFont = new System.Drawing.Font("Courier New", 10, System.Drawing.FontStyle.Italic);
            System.Drawing.Font ValoreEquiFont = new System.Drawing.Font("Courier New", 14);
            System.Drawing.Font ValoreFont = new System.Drawing.Font("Arial", 14);
            System.Drawing.Font ValoreFontSmall = new System.Drawing.Font("Arial", 11);

            // 1) Header biglietto [A32 1/4]
            e.Graphics.DrawString("VASSOIO: ", EtichettaFont, System.Drawing.Brushes.Black, new System.Drawing.PointF(5, 5));
            e.Graphics.DrawString(
                CodiceComanda + (NTotaleVassoi != 1 ? " (" + Progressivo.ToString() + "/" + NTotaleVassoi.ToString() + ")" : ""),
                ValoreEquiFont, System.Drawing.Brushes.Black, new System.Drawing.PointF(95, 4));
            e.Graphics.DrawString("T." + TavoloAssegnato, new System.Drawing.Font("Arial Black", 30), System.Drawing.Brushes.Black, new System.Drawing.PointF(30, 15));
            iTextSharp.text.pdf.Barcode128 b = new iTextSharp.text.pdf.Barcode128();
            b.Code = new TARLib.Operazioni.Operazione_Vassoio(VassoioID.Value).BarcodeString;
            System.Drawing.Image image = b.CreateDrawingImage(System.Drawing.Color.Black, System.Drawing.Color.White);
            e.Graphics.DrawImage(image, 220, 5, 150, 50);
            e.Graphics.DrawLine(System.Drawing.Pens.Black, new System.Drawing.Point(0, 80), new System.Drawing.Point(390, 80));

            // 2) Punto di distribuzione ["Ristorante"]
            e.Graphics.DrawString(PuntoDiDistribuzione.Descrizione.ToUpper(), PuntoDistribuzioneFont, System.Drawing.Brushes.Black, new System.Drawing.PointF(10, 80));

            e.Graphics.DrawLine(System.Drawing.Pens.Black, new System.Drawing.Point(0, 110), new System.Drawing.Point(390, 110));

            // 3) Area con i prodotti ["Quantita | Descrizione | Importo"]
            // 0, 120 --> 390, 420
            int i = 0;
            if (VociComanda.Count >= 1)
            {
                // Quante comande hanno delle note?
                int NNote = VociComanda.Where(o => !String.IsNullOrEmpty(o.Note)).Count();
                int stepHeight = (300 / (VociComanda.Count + NNote / 2)) < 35 ? (300 / (VociComanda.Count + NNote / 2)) : 35;
                foreach (VoceComanda v in VociComanda)
                {
                    e.Graphics.DrawString(v.Quantita.ToString().PadLeft(2, ' '), ValoreEquiFont, System.Drawing.Brushes.Black, new System.Drawing.PointF(2, 130 + stepHeight * i));

                    e.Graphics.DrawString(v.NomeProdotto, ValoreFont, System.Drawing.Brushes.Black, new System.Drawing.PointF(40, 130 + stepHeight * i));

                    //e.Graphics.DrawString(String.Format("{0:0.00} €", v.SubTotale).PadLeft(8, ' '), ValoreEquiFont, System.Drawing.Brushes.Black, new System.Drawing.PointF(280, 130 + stepHeight * i));

                    if (!String.IsNullOrEmpty(v.Note))
                    {
                        e.Graphics.DrawString(v.Note, NoteFont, System.Drawing.Brushes.Black, new System.Drawing.PointF(45, 130 + stepHeight * ((float)i + (float)0.5)));
                    }

                    i++;
                }
            }

            // 4) Note vassoio (= comanda)
            // Note
            if (!String.IsNullOrEmpty(Note))
            {
                e.Graphics.FillRectangle(System.Drawing.Brushes.LightGray, new System.Drawing.Rectangle(2, 450, 386, 20));
                e.Graphics.DrawString(Note.ToLower(), EvidenziatoFont, System.Drawing.Brushes.Black, new System.Drawing.RectangleF(5, 451, 386, 20));
            }

            // Data
            e.Graphics.DrawString(String.Format("Creato: {0:dd/MM/yyyy HH:mm}", this.DataOra), EtichettaFont, System.Drawing.Brushes.Black, new System.Drawing.PointF(10, 480));
            e.Graphics.DrawString(String.Format("Stampato: {0:dd/MM/yyyy HH:mm}", DateTime.Now), EtichettaFont, System.Drawing.Brushes.Black, new System.Drawing.PointF(10, 510));

            e.Graphics.DrawLine(System.Drawing.Pens.Black, new System.Drawing.Point(0, 470), new System.Drawing.Point(390, 470));
        }

        public void SetPrinted(DateTime dataOra, string autore, bool esito, string stampante)
        {
            // Salvataggio su DB
            if (VassoioID.HasValue)
            {
                using (SqlConnection connection = new SqlConnection(Database.GetDBConnectionString()))
                {
                    connection.Open();
                    SqlCommand cmd = new SqlCommand();
                    cmd.Connection = connection;
                    cmd.CommandText = "[Cucina].[SP_VassoioStampaRemota_I]";
                    cmd.CommandType = System.Data.CommandType.StoredProcedure;

                    cmd.Parameters.Add(new SqlParameter("@VassoioStampaRemotaID", System.Data.SqlDbType.Int) { Direction = System.Data.ParameterDirection.Output });

                    cmd.Parameters.Add(new SqlParameter("@VassoioID", System.Data.SqlDbType.Int) { Value = VassoioID });
                    cmd.Parameters.Add(new SqlParameter("@DataOra", System.Data.SqlDbType.DateTime) { Value = dataOra });
                    cmd.Parameters.Add(new SqlParameter("@Autore", System.Data.SqlDbType.NVarChar, 200) { Value = autore });
                    cmd.Parameters.Add(new SqlParameter("@Stampante", System.Data.SqlDbType.NVarChar, 200) { Value = stampante });
                    cmd.Parameters.Add(new SqlParameter("@Esito", System.Data.SqlDbType.Bit) { Value = esito });

                    try
                    {
                        cmd.ExecuteNonQuery();
                    }
                    catch (Exception ex)
                    {

                        throw ex;
                    }
                    finally
                    {
                        connection.Close();
                        cmd.Dispose();
                    }
                }
            }
            else
            {
                throw new Exception("Impossibile effettuare stampa di vassoi non ancora salvate");
            }
        }

        public void SetDelivered(DateTime dataOra, string autore, bool esito)
        {
            if (VassoioID.HasValue)
            {
                using (SqlConnection connection = new SqlConnection(Database.GetDBConnectionString()))
                {
                    connection.Open();
                    SqlCommand cmd = new SqlCommand();
                    cmd.Connection = connection;
                    cmd.CommandText = "[Cucina].[SP_VassoioConsegna_I]";
                    cmd.CommandType = System.Data.CommandType.StoredProcedure;

                    cmd.Parameters.Add(new SqlParameter("@VassoioConsegnaID", System.Data.SqlDbType.Int) { Direction = System.Data.ParameterDirection.Output });

                    cmd.Parameters.Add(new SqlParameter("@VassoioID", System.Data.SqlDbType.Int) { Value = VassoioID });
                    cmd.Parameters.Add(new SqlParameter("@DataOra", System.Data.SqlDbType.DateTime) { Value = dataOra });
                    cmd.Parameters.Add(new SqlParameter("@Autore", System.Data.SqlDbType.NVarChar, 200) { Value = autore });
                    cmd.Parameters.Add(new SqlParameter("@Esito", System.Data.SqlDbType.Bit) { Value = esito });

                    try
                    {
                        cmd.ExecuteNonQuery();
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    finally
                    {
                        connection.Close();
                        cmd.Dispose();
                    }
                }
            }
            else
            {
                throw new Exception("Impossibile effettuare consegna di vassoi non ancora salvati");
            }
        }
    }
}
